#pragma once

#include <algorithm/analytical_model/algorithm/cuda/math/vector/Common.cuh>
#include <algorithm/shared/utils/GenericVectorMath.h>
#include <utils/config.h>

inline HOT_FUNCTION __host__ __device__ auto make_float2(const float& s) -> float2
{
    return ::make_float2(s, s);
}
inline HOT_FUNCTION __host__ __device__ auto make_float2(const int2&& a) -> float2
{
    return ::make_float2(float(a.x), float(a.y));
}

inline HOT_FUNCTION __host__ __device__ auto operator-(const float2& a) -> float2
{
    return solar::internal::vector::negate(a);
}

inline HOT_FUNCTION __host__ __device__ auto operator+(const float2& a, const float2& b) -> float2
{
    return solar::internal::vector::plus(a, b);
}

inline HOT_FUNCTION __host__ __device__ auto operator+(const float2& a, const float& b) -> float2
{
    return solar::internal::vector::plus(a, b);
}

inline HOT_FUNCTION __host__ __device__ auto operator+(const float& b, const float2& a) -> float2
{
    return solar::internal::vector::plus(a, b);
}

inline HOT_FUNCTION __host__ __device__ void operator+=(float2& a, const float2& b)
{
    solar::internal::vector::plusSelf(a, b);
}

inline HOT_FUNCTION __host__ __device__ auto operator-(const float2& a, const float2& b) -> float2
{
    return solar::internal::vector::minus(a, b);
}

inline HOT_FUNCTION __host__ __device__ auto operator-(const float2& a, const float& b) -> float2
{
    return solar::internal::vector::minus(a, b);
}

inline HOT_FUNCTION __host__ __device__ auto operator-(const float& b, const float2& a) -> float2
{
    return solar::internal::vector::minus(a, b);
}

inline HOT_FUNCTION __host__ __device__ void operator-=(float2& a, const float2& b)
{
    solar::internal::vector::minusSelf(a, b);
}

inline HOT_FUNCTION __host__ __device__ auto operator*(const float2& a, const float2& b) -> float2
{
    return solar::internal::vector::multiply(a, b);
}

inline HOT_FUNCTION __host__ __device__ auto operator*(const float2& a, const float& s) -> float2
{
    return solar::internal::vector::multiply(a, s);
}

inline HOT_FUNCTION __host__ __device__ auto operator*(const float& s, const float2& a) -> float2
{
    return solar::internal::vector::multiply(a, s);
}

inline HOT_FUNCTION __host__ __device__ void operator*=(float2& a, const float& s)
{
    solar::internal::vector::multiplySelf(a, s);
}

inline HOT_FUNCTION __host__ __device__ auto operator/(const float2& a, const float2& b) -> float2
{
#ifdef __CUDA_ARCH__
    return solar::internal::vector::cuda::divide(a, b);
#else
    return solar::internal::vector::divide(a, b);
#endif
}

inline HOT_FUNCTION __host__ __device__ auto operator/(const float2& a, const float& s) -> float2
{
#ifdef __CUDA_ARCH__
    return solar::internal::vector::cuda::divide(a, s);
#else
    return solar::internal::vector::divide(a, s);
#endif
}

inline HOT_FUNCTION __host__ __device__ auto operator/(const float& s, const float2& a) -> float2
{
#ifdef __CUDA_ARCH__
    return solar::internal::vector::cuda::divide(a, s);
#else
    return solar::internal::vector::divide(a, s);
#endif
}

inline HOT_FUNCTION __host__ __device__ void operator/=(float2& a, const float& s)
{
#ifdef __CUDA_ARCH__
    solar::internal::vector::cuda::divideSelf(a, s);
#else
    solar::internal::vector::divideSelf(a, s);
#endif
}

inline HOT_FUNCTION __device__ __host__ auto lerp(const float2& a, const float2& b,
                                                  const float& t) -> float2
{
    return solar::internal::vector::lerp(a, b, t);
}

inline HOT_FUNCTION __device__ __host__ auto clamp(const float2& v, const float& a,
                                                   const float& b) -> float2
{
    return solar::internal::vector::clamp(v, a, b);
}

inline HOT_FUNCTION __device__ __host__ auto clamp(const float2& v, const float2& a,
                                                   const float2& b) -> float2
{
    return solar::internal::vector::clamp(v, a, b);
}

inline HOT_FUNCTION __host__ __device__ auto dot(const float2& a, const float2& b) -> float
{
    return solar::internal::vector::dot(a, b);
}

inline HOT_FUNCTION __host__ __device__ auto length(const float2& v) -> float
{
    return solar::internal::vector::length(v);
}

inline HOT_FUNCTION __host__ __device__ auto normalize(const float2& v) -> float2
{
    return solar::internal::vector::normalize(v);
}

inline HOT_FUNCTION __host__ __device__ auto floor(const float2& v) -> float2
{
    return solar::internal::vector::floor(v);
}

inline HOT_FUNCTION __host__ __device__ auto reflect(const float2& i, const float2& n) -> float2
{
    return solar::internal::vector::reflect(i, n);
}

inline HOT_FUNCTION __host__ __device__ auto fabs(const float2& v) -> float2
{
    return solar::internal::vector::abs(v);
}
